package com.alfy.sbdemo.websocketdemo.demo2;

import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;

import javax.servlet.http.HttpServletRequest;
import java.util.Map;

/**
 * 本类是继承与 HttpSessionHandshakeInterceptor 类的 WebSocket 拦截器类。
 * 最终实现于 HandshakeInterceptor 接口，它是 WebSocket 握手请求的拦截器。可用于检查握手请求和响应，以及将属性传递给目标 WebSocketHandler。
 */
public class MyHandshakeInterceptor extends HttpSessionHandshakeInterceptor {

    /**
     * 在处理握手之前调用。这里回传的 ServerHttpRequest(实现类为 ServletServerHttpRequest)包裹了 HttpServletRequest
     *
     * @param request    当前请求
     * @param response   当前响应
     * @param wsHandler  目标 WebSocket 处理程序
     * @param attributes 要与 WebSocket 会话关联的 HTTP 握手中的属性; 将复制提供的属性，不使用原始地图。
     * @return boolean 继续握手 （true） 还是中止 （false）
     * @throws Exception 异常
     */
    @Override
    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
        System.out.println("拦截器前置触发, wsHandler: " + wsHandler + ", attributes: " + attributes + ", RequestAttributes: " + RequestContextHolder.getRequestAttributes());
        // 也可以从 session 中获取用户信息(也可以使用请求头放 token,只要能获取到用户都 ok)
        HttpServletRequest servletRequest = ((ServletServerHttpRequest) request).getServletRequest();
        String name = servletRequest.getParameter("name");
        System.out.println("拦截器前置触发, 获取参数 name: " + name);
        synchronized (this) {
            if (name != null && name.startsWith("ws")){
                System.out.println("拦截器前置触发, 基础校验通过（" + name + "）, 允许建立链接");
                // 在 WebSocket 连接建立时获取地址参数和路径参数，可以通过设置 HandshakeInterceptor 来捕获请求参数，并将其添加到 WebSocket 会话的属性中。
                attributes.put("name", name);
                // 获取路径参数（假设路径为 /ws/{userId}）
                String test = servletRequest.getRequestURI().split("/")[3];
                attributes.put("test", test);
                return true;
            }
            System.out.println("拦截器前置触发, 校验不通过（" + name + ")");
            return false;
        }
        // return super.beforeHandshake(request, response, wsHandler, attributes);

    }

    /**
     * 握手完成后调用。响应状态和标头指示握手的结果，即握手是否成功。
     *
     * @param request   当前请求
     * @param response  当前响应
     * @param wsHandler 目标 WebSocket 处理程序
     * @param ex 握手时引发的异常，或者 null 如果没有异常
     */
    @Override
    public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception ex) {
        System.out.println("拦截器后置触发, " + ", " + wsHandler + ", ex: " + ex + ", RequestAttributes: " + RequestContextHolder.getRequestAttributes());
        super.afterHandshake(request, response, wsHandler, ex);
    }
}
